`include "common_header.verilog"

//  *************************************************************************
//  File : block_sync_1040.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited. 
//  Copyright (c) 2011 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Denis Poverennyy
//  info@morethanip.com
//  *************************************************************************
//  Description: 40G PCS Receive Core : Block Sync Module Top Structure
//  Version    : $Id: block_sync_1040.v,v 1.2 2012/10/29 12:46:40 dk Exp $
//  *************************************************************************

module block_sync_1040 (

   reset,
   clk,
   ck_ena,
   mode40,
   gctl_stop,
   sig_det,
   data_in,
   block_lock,
   sync_lost,
   data_valid,
   data_valid_scr,
   data_out,
   sh_out);
   
input   reset;          //  asynch reset
input   clk;            //  system clock
input   ck_ena;         //  clock enable
input   mode40;         //  operate according to 40G/100G(1), else 10G(0)
input   gctl_stop;      //  stop slip and reset slip control to begin
input   sig_det;        //  if 0 lane not ready
input   [65:0] data_in; //  Data input
output  block_lock;     //  Lock state reached
output  sync_lost;      //  Sync lost pulse
output  data_valid;     //  Data and Sync header valid for all after de-scrambler
output  data_valid_scr; //  Data and Sync header valid for de-scrambler
output  [63:0] data_out;//  Data out
output  [1:0] sh_out;   //  Sync header out

wire    block_lock; 
reg     sync_lost; 
wire    data_valid; 
wire    data_valid_scr; 
wire    [63:0] data_out; 
wire    [1:0] sh_out; 


wire    [6:0] mux_data_cd;      //  Command of Data Mux
wire    [1:0] sync_tst;         //  Sync header to be tested
wire    ck_ena_mux66;           //  data valid after mux66
wire    sh_ok;                  //  Sync header good or not
wire    sh_val;                 //  Sync header valid
wire    slip;                   //  Slip - next candidate
wire    block_lock_s;           //  Lock state reached
reg     block_lock_p;           //  substitute for pipeline delay introduced until decoder acts

// =============================================================
//     MUX_66 => used as pipeline: all blocks after it run from
//     output valid instead ck_ena!
// =============================================================
mux_661 U_MUX_66 (

          .reset(reset),
          .clk(clk),
          .ck_ena(ck_ena),
          .data_in(data_in),
          .mux_data_cd(mux_data_cd),
          .data_out(data_out),
          .sh_out(sh_out),
          .sync_tst(sync_tst),
          .data_out_val(ck_ena_mux66));

// ---------------------
//  Lock state reached
// ---------------------

// ---------------------
//  delay block lock for all stages after block-sync to compensate for pipeline delay.
//  On block sync we enable it immediately, as scrambler is already valid for the last cycles
//  On loss of sync we need to wait until the last block that caused block lock deassertion went down to the decoder
//  to properly count the error.

assign block_lock = block_lock_s; 

always @(posedge reset or posedge clk)
   begin : p_lock_d
   if (reset == 1'b 1)
      begin
      block_lock_p <= 1'b 0;	
      sync_lost <= 1'b 0;	
      end
   else
      begin
      if (ck_ena_mux66 == 1'b 1)
         begin
         block_lock_p <= block_lock_s;	

                //  indicate loss of sync at very end
         if (block_lock_p == 1'b 1 & block_lock_s == 1'b 0)
            begin
            sync_lost <= 1'b 1;	
            end
         else
            begin
            sync_lost <= 1'b 0;	
            end

         end
      end
   end


// =============================================================
// =============================================================
//     sync_detect 
// =============================================================
sync_detect_1040 U_SYNC_DETECT (
          .reset(reset),
          .clk(clk),
          .ck_ena(ck_ena_mux66),
          .mode40(mode40),
          .sh_ok(sh_ok),
          .sh_val(sh_val),
          .sig_det(sig_det),
          .slip(slip),
          .block_lock(block_lock_s));
          

// =============================================================
// =============================================================
//     gear_control
// =============================================================
gear_control_f U_GEAR_CONTROL (	

          .reset(reset),
          .clk(clk),
          .ck_ena(ck_ena_mux66),
          .gctl_stop(gctl_stop),
          .slip(slip),
          .sync_tst(sync_tst),
          .block_lock(block_lock_s),
          .sh_ok(sh_ok),
          .sh_val(sh_val),
          .mux_data_cd(mux_data_cd),
          .data_valid(), // data_valid),
          .data_valid_scr()); //data_valid_scr));

assign data_valid_scr = ck_ena_mux66;   // not delayed!
assign data_valid     = ck_ena_mux66 & block_lock_s;    // combinatorial on dval is bad but we know its not used by many
          
          
 

endmodule // module block_sync_40g

